package game;

import java.util.ArrayList;
import java.util.List;

import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;

import sound.SoundManager;
import util.Vector2D;
import entities.Entity;
import entities.Player;

public class Level {

	private List<Entity> entities;

	private List<Entity> spawnList;
	private List<Entity> killList;

	private List<EnemyWave> waves;
	private Player player;

	private int currentWaveID;

	private boolean finished;
	
	private int displayWaveMessageTimer;
	
	private float scrollingSpeed = -200.0f;
	private float scrollingX;
	private Image bgImage;

	public Level(Player player, List<EnemyWave> waves) {
		this.waves = waves;
		this.player = player;
		entities = new ArrayList<Entity>();
		killList = new ArrayList<Entity>();
		spawnList = new ArrayList<Entity>();
		try {
			bgImage = new Image("res/background2.png");
		} catch (SlickException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Should only be called via Level.spawnEntity()!
	 * 
	 * @param entity
	 */
	public void addEntity(Entity entity) {
		spawnList.add(entity);
	}

	public void removeEntity(Entity e) {
		killList.add(e);
	}

	public void update(GameContainer gc, int delta) {
	
		if (!finished) {
			for (Entity e : entities) {
				e.update(gc, delta);
			}
			for (Entity e : spawnList) {
				// System.out.println("Entity spawned: " + e.getName());
				entities.add(e);
			}
			for (Entity e : killList) {
				// System.out.println("Entity killed: " + e.getName());
				entities.remove(e);
			}
			killList.clear();
			spawnList.clear();
			
			if (displayWaveMessageTimer > 0) {
				displayWaveMessageTimer -= delta;
			}
			
			scrollingX += scrollingSpeed * (delta / 1000.0f);
			if (scrollingX <= -bgImage.getWidth()) {
				scrollingX = 0;
			}

			EnemyWave wave = waves.get(currentWaveID);
			wave.update(gc, delta);
			if (wave.isDefeated()) {
				System.out.println("Wave defeated!");
				SoundManager.getSoundManager().playSound(SoundManager.waveComplete, 1f);
				currentWaveID++;
				System.out.println("Neue Wave:" + currentWaveID);
				if (currentWaveID >= waves.size()) {
					finished = true;
				} else {
					enterWave(currentWaveID);
				}
			}
		} 
	}

	public void enterWave(int waveID) {
		waves.get(waveID).init(this);
		displayWaveMessageTimer = 2000;
	}

	public boolean finished() {
		return finished;
	}

	public void render(GameContainer gc, Graphics g) {
		bgImage.draw(scrollingX, 0, bgImage.getWidth(), gc.getHeight());
		bgImage.draw(scrollingX + bgImage.getWidth(), 0, bgImage.getWidth(), gc.getHeight());
		for (Entity e : entities) {
			if (e != null) {
				e.render(gc, g);
			}
			if (displayWaveMessageTimer > 0) {
				g.setColor(new Color(0x111111));
				g.drawString("Wave " + (currentWaveID + 1), gc.getWidth() / 2, gc.getHeight() / 2);
			}
		}
	}

	public Player getPlayer() {
		return player;
	}

	public boolean isActive(Entity e) {
		return entities.contains(e) || spawnList.contains(e);
	}

	public List<Entity> getCollisions(Entity e) {
		ArrayList<Entity> collisions = new ArrayList<Entity>();
		for (Entity other : entities) {
			if (e != other && isActive(other) && e.collidesWith(other)) {
				collisions.add(other);
			}
		}
		return collisions;
	}

	public void reset(GameContainer gc) throws SlickException {
		finished = false;
		currentWaveID = 0;
		entities.clear();
		spawnList.clear();
		killList.clear();
		scrollingX = 0;
		player.spawn(this,
				new Vector2D(2 * player.getImage().getWidth(), gc.getHeight()
						/ 2 - player.getImage().getHeight() / 2));
		waves.get(currentWaveID).reset();
		waves = WaveEditor.generateWaves(player);
		enterWave(currentWaveID);
	}

}
